package com.wenlin.myproduction.widget;

import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Shader;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;

import androidx.annotation.ColorInt;
import androidx.annotation.Nullable;

import com.wenlin.myproduction.R;
import com.wenlin.myproduction.util.Checker;
import com.wenlin.myproduction.util.UI;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class HistogramView extends View {
    private int viewWidth = (int) UI.getPx(R.dimen.wpx960);//直接使用固定的宽高
    private int viewHeight = (int) UI.getPx(R.dimen.wpx700);
    private Paint paint;//画笔
    private Rect rect;//算字的宽高用的
    private TextPaint textPaint;//写字的画笔
    @ColorInt
    private int textColor;//文字颜色
    private float[] arrHeight;//垂直方向上的基准线数组
    private float[] arrWidth;//水平方向上的基准线数组
    private int max;//最大值，经过处理后是4的倍数
    private LinearGradient[] arrLinearGradient;//渐变色
    private List<HistogramBean> list;//数据集合
    private float histogramWidth = UI.getPx(R.dimen.wpx34);//每个柱子的宽度
    private float textSizeTitle = UI.getPx(R.dimen.wpx32);//底部项目的字号
    private float textSizeLabel = UI.getPx(R.dimen.wpx32);//纵坐标的标签的字号
    private float textSizeValue = UI.getPx(R.dimen.wpx36);//柱子上的数字的字号
    private float paddingEnd = UI.getPx(R.dimen.wpx32);//右侧距离右侧边界的距离
    private ValueAnimator valueAnimator;//动画
    private float valueFloat;//动画用的
    private boolean release;//是否释放

    public HistogramView(Context context) {
        this(context, null);
    }

    public HistogramView(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.HistogramView);
        textColor = ta.getColor(R.styleable.HistogramView_hv_text_color, Color.WHITE);
        ta.recycle();
        initialize();
    }

    private void initialize() {
        //画笔
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setColor(textColor);
        paint.setDither(true);
        paint.setStyle(Paint.Style.FILL_AND_STROKE);
        //文本画笔
        textPaint = new TextPaint();
        textPaint.setAntiAlias(true);
        textPaint.setDither(true);
        textPaint.setColor(textColor);
        textPaint.setStyle(Paint.Style.FILL_AND_STROKE);
        //
        rect = new Rect();
        //计算并填充数组
        arrHeight = new float[4];
        arrWidth = new float[4];
        for (int i = 0; i < 4; i++) {
            arrHeight[i] = (i + 1) * viewHeight / 5f;
            arrWidth[i] = (i + 1) * (viewWidth - paddingEnd) / 5f;
        }
        //渐变色
        arrLinearGradient = new LinearGradient[4];
        arrLinearGradient[0] = new LinearGradient(0f, arrHeight[3], 0f, 0f,
                Color.parseColor("#FF1dc9e3"),//蓝色
                Color.parseColor("#FF1de6ba"),//绿色
                Shader.TileMode.CLAMP
        );
        arrLinearGradient[1] = new LinearGradient(0f, arrHeight[3], 0f, 0f,
                Color.parseColor("#FF8A9DD2"),//紫色
                Color.parseColor("#FFDBD3F0"),//紫色偏白
                Shader.TileMode.CLAMP
        );
        arrLinearGradient[2] = new LinearGradient(0f, arrHeight[3], 0f, 0f,
                Color.parseColor("#FFFF4839"),//红色
                Color.parseColor("#FFFFB988"),//橙色
                Shader.TileMode.CLAMP
        );
        arrLinearGradient[3] = new LinearGradient(0f, arrHeight[3], 0f, 0f,
                Color.parseColor("#FF049DF7"),//蓝色
                Color.parseColor("#FF62C8F8"),//淡蓝色
                Shader.TileMode.CLAMP
        );
        //
        list = new ArrayList<>();
    }

    /**
     * 设置随机数据
     */
    @Deprecated
    public void setRandomData() {
        String[] titles = {"今日阅读", "书目", "英语农场", "磨耳朵"};
        List<HistogramBean> newList = new ArrayList<>();
        Random random = new Random();
        for (String title : titles) {
            newList.add(new HistogramBean(title, random.nextInt(100)));
        }
        setData(newList);
    }

    /**
     * 设置数据
     *
     * @param list 数据集合
     */
    public void setData(List<HistogramBean> list) {
        if (release) return;
        this.list = list;
        max = 0;
        if (Checker.hasList(list)) {
            for (int i = 0; i < list.size(); i++) {
                if (i == 0) max = list.get(i).min;
                max = Math.max(list.get(i).min, max);
            }
        }
        if (max < 4) max = 4;
        //让最大值能被4整除
        while (max % 4 != 0) {
            max++;
        }
        startAnimation();
    }

    /**
     * 开始动画
     */
    public void startAnimation() {
        if (release) return;
        if (Checker.hasNoList(list)) return;
        if (Checker.notNull(valueAnimator) && valueAnimator.isRunning())
            valueAnimator.cancel();
        valueAnimator = null;
        valueAnimator = ValueAnimator.ofFloat(0, 1);
        valueAnimator.addUpdateListener(animation -> {
            valueFloat = (float) animation.getAnimatedValue();
            invalidate();
        });
        valueAnimator.setDuration(1000);
        valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
        valueAnimator.start();
    }

    private void release() {
        release = true;
        if (Checker.notNull(valueAnimator)) valueAnimator.cancel();
        valueAnimator = null;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (release) return;
        textPaint.setTextSize(textSizeValue);
        textPaint.getTextBounds("4", 0, 1, rect);
        canvas.translate(0, rect.height() + UI.getPx(R.dimen.wpx8));//画布平移一下
//        canvas.drawColor(Color.CYAN);
        //lines
        for (int i = 0; i < arrHeight.length; i++) {
            canvas.drawLine(arrWidth[0], arrHeight[i], viewWidth - paddingEnd, arrHeight[i], textPaint);
            String title = (int) (max / 4f * (3 - i)) + "min";
            textPaint.setTextSize(textSizeLabel);
            textPaint.getTextBounds(title, 0, title.length(), rect);
            canvas.drawText(title, arrWidth[0] - rect.width() - 20, arrHeight[i] + rect.height() / 2f, textPaint);
        }
        //title and value
        for (int i = 0; i < arrWidth.length; i++) {
            if (Checker.hasList(list) && list.size() > i) {
                //画渐变色柱子
                paint.setShader(arrLinearGradient[i]);
                float delta = arrHeight[3];
                if (Checker.notNull(valueAnimator) && valueAnimator.isRunning())
                    delta *= valueFloat;
                float top = arrHeight[3] - (list.get(i).min / (float) max * delta);
                if (top == arrHeight[3]) top -= 2;//如果分钟数是0，则强制画一个小小的柱子，不至于什么都没有
                canvas.drawRoundRect(arrWidth[i] + viewWidth / 10f - histogramWidth / 2f, top, arrWidth[i] + viewWidth / 10f + histogramWidth / 2f, arrHeight[3], 2, 2, paint);
                //画柱子顶部的数字
                String strMin = String.valueOf(list.get(i).min);
                textPaint.setTextSize(textSizeValue);
                textPaint.getTextBounds(strMin, 0, strMin.length(), rect);
                canvas.drawText(strMin, arrWidth[i] + viewWidth / 10f - rect.width() / 2f, top - 5, textPaint);
                //画底部的title
                String title = list.get(i).title;
                textPaint.setTextSize(textSizeTitle);
                textPaint.getTextBounds(title, 0, title.length(), rect);
                canvas.drawText(title, arrWidth[i] + viewWidth / 10f - rect.width() / 2f, arrHeight[3] + viewHeight / 10f - rect.height() / 2f, textPaint);
            }
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measure(widthMeasureSpec, true), measure(heightMeasureSpec, false));
    }

    /**
     * 获取宽或者高
     *
     * @param measureSpec 测量单位
     * @param isWidSpec   是宽还是高
     * @return 所求
     */
    private int measure(int measureSpec, boolean isWidSpec) {
        int result;
        int mode = MeasureSpec.getMode(measureSpec);
        int size = MeasureSpec.getSize(measureSpec);
        if (mode == MeasureSpec.EXACTLY) {
            result = size;
        } else {
            result = isWidSpec ? viewWidth : viewHeight;
            if (mode == MeasureSpec.AT_MOST) result = Math.min(result, size);
        }
        return result;
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        release();
    }

    public static class HistogramBean {
        String title;
        int min;

        public HistogramBean(String title, int min) {
            this.title = title;
            this.min = min;
        }
    }
}
